
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
                            main.c
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
                                                    Forrest Yu, 2005
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/

#include "type.h"
#include "const.h"
#include "protect.h"
//#include "proto.h"
#include "string.h"
#include "proc.h"
#include "proto.h"
#include "global.h"


/*======================================================================*
                            kernel_main
 *======================================================================*/
PUBLIC int kernel_main()
{
	disp_str("-----\"kernel_main\" begins-----\n");
	//clear_consol();

	TASK*		p_task		= task_table;
	PROCESS*	p_proc		= proc_table;
	char*		p_task_stack	= task_stack + STACK_SIZE_TOTAL;
	u16		selector_ldt	= SELECTOR_LDT_FIRST;
	int i;
	for (i = 0; i < NR_TASKS; i++) {
		strcpy(p_proc->p_name, p_task->name);	// name of the process
		p_proc->pid = i;			// pid

		p_proc->ldt_sel = selector_ldt;

		memcpy(&p_proc->ldts[0], &gdt[SELECTOR_KERNEL_CS >> 3],
		       sizeof(DESCRIPTOR));
		p_proc->ldts[0].attr1 = DA_C | PRIVILEGE_TASK << 5;
		memcpy(&p_proc->ldts[1], &gdt[SELECTOR_KERNEL_DS >> 3],
		       sizeof(DESCRIPTOR));
		p_proc->ldts[1].attr1 = DA_DRW | PRIVILEGE_TASK << 5;
		p_proc->regs.cs	= ((8 * 0) & SA_RPL_MASK & SA_TI_MASK)
			| SA_TIL | RPL_TASK;
		p_proc->regs.ds	= ((8 * 1) & SA_RPL_MASK & SA_TI_MASK)
			| SA_TIL | RPL_TASK;
		p_proc->regs.es	= ((8 * 1) & SA_RPL_MASK & SA_TI_MASK)
			| SA_TIL | RPL_TASK;
		p_proc->regs.fs	= ((8 * 1) & SA_RPL_MASK & SA_TI_MASK)
			| SA_TIL | RPL_TASK;
		p_proc->regs.ss	= ((8 * 1) & SA_RPL_MASK & SA_TI_MASK)
			| SA_TIL | RPL_TASK;
		p_proc->regs.gs	= (SELECTOR_KERNEL_GS & SA_RPL_MASK)
			| RPL_TASK;

		p_proc->regs.eip = (u32)p_task->initial_eip;
		p_proc->regs.esp = (u32)p_task_stack;
		p_proc->regs.eflags = 0x1202; /* IF=1, IOPL=1 */
		
		p_proc->sleep_ticks=0;//将睡眠时间设置位0
		p_proc->has_began=0;

		p_task_stack -= p_task->stacksize;
		p_proc++;
		p_task++;
		selector_ldt += 1 << 3;
	}
	
	work_time_unit=1000*HZ/1000;//设置工作时间单位为1ms

	proc_table[0].ticks = proc_table[0].priority = proc_table[0].total_ticks = 2*work_time_unit;
	proc_table[1].ticks = proc_table[1].priority = proc_table[1].total_ticks = 3*work_time_unit;
	proc_table[2].ticks = proc_table[2].priority = proc_table[2].total_ticks = 3*work_time_unit;
	proc_table[3].ticks = proc_table[3].priority = proc_table[3].total_ticks = 3*work_time_unit;
	proc_table[4].ticks = proc_table[4].priority = proc_table[4].total_ticks = 4*work_time_unit;
	proc_table[5].ticks = proc_table[5].priority = proc_table[5].total_ticks = 1*work_time_unit;

	/*proc_table[0].sleep_ticks = 3;
	proc_table[1].sleep_ticks = 0;
	proc_table[2].sleep_ticks = 0;
	proc_table[3].sleep_ticks = 0;*/
	
	//初始化信号量
	r_mutex.s_num=1;
	r_mutex.p_procs_len=0;
	w_mutex.s_num=1;
	w_mutex.p_procs_len=0;
	s.s_num=1;
	s.p_procs_len=0;
	r_count=0;//读进程计数
	MAX_READ_NUM=3;
	
	k_reenter = 0;
	ticks = 0;

	p_proc_ready	= proc_table;
	//schedule();

        /* 初始化 8253 PIT */
        out_byte(TIMER_MODE, RATE_GENERATOR);
        out_byte(TIMER0, (u8) (TIMER_FREQ/HZ) );
        out_byte(TIMER0, (u8) ((TIMER_FREQ/HZ) >> 8));

        put_irq_handler(CLOCK_IRQ, clock_handler); /* 设定时钟中断处理程序 */
        enable_irq(CLOCK_IRQ);                     /* 让8259A可以接收时钟中断 */

	restart();

	while(1){}
}

/*PUBLIC void set_global_str(char* str){
	int i=0;
	while(str[i]!='\0'){
		global_str[i]=str[i];
		i++;
	}
	global_str[i]='\0';
}*/


/*======================================================================*
                               TestA
 *======================================================================*/
void TestA()
{
	int i = 0;
	while (1) {
		if(p_proc_ready->ticks == p_proc_ready->total_ticks){
			if(!p_proc_ready->has_began){
				p_proc_ready->has_began=1;
				
				//p_sema(&s);
				
				p_sema(&r_mutex);
				if(r_count==0){p_sema(&w_mutex);}
				r_count++;
				if(r_count < MAX_READ_NUM){//如果已经达到最大读数量，就不再释放资源
					v_sema(&r_mutex);
				}
	
				//v_sema(&s);
					
				disp_color_str("A: r begin",RED_COLOR);
				disp_str(" / ");
			}
		}
		else if(p_proc_ready->ticks == 1){
			p_proc_ready->has_began=0;
			
			disp_color_str("A: r end",RED_COLOR);
			disp_str(" / ");
			
			if(r_count == MAX_READ_NUM){
				v_sema(&r_mutex);
			}
			r_count--;
			if(r_count==0){v_sema(&w_mutex);}
			
			/*p_sema(&r_mutex);
			r_count--;
			if(r_count==0){v_sema(&w_mutex);}
			v_sema(&r_mutex);*/
		}
		milli_delay(10);
	}
}

/*======================================================================*
                               TestB
 *======================================================================*/
void TestB()
{
	int i = 0x1000;
	while(1){
		if(p_proc_ready->ticks == p_proc_ready->total_ticks){
			if(!p_proc_ready->has_began){
				p_proc_ready->has_began=1;
				
				//p_sema(&s);
				
				p_sema(&r_mutex);
				if(r_count==0){p_sema(&w_mutex);}
				r_count++;
				if(r_count < MAX_READ_NUM){//如果已经达到最大读数量，就不再释放资源
					v_sema(&r_mutex);
				}
				
				//v_sema(&s);

				disp_color_str("B: r begin",RED_COLOR);
				disp_str(" / ");
			}
		}
		else if(p_proc_ready->ticks == 1){
			p_proc_ready->has_began=0;
			
			disp_color_str("B: r end",RED_COLOR);
			disp_str(" / ");
			
			if(r_count == MAX_READ_NUM){
				v_sema(&r_mutex);
			}
			r_count--;
			if(r_count==0){v_sema(&w_mutex);}
			
			/*if(r_count == MAX_READ_NUM){//该读进程结束时，如果已经达到最大读数量，就释放资源
				v_sema(&r_mutex);
			}
			p_sema(&r_mutex);
			r_count--;
			if(r_count==0){v_sema(&w_mutex);}
			v_sema(&r_mutex);*/
		}
		milli_delay(10);
	}
}

/*======================================================================*
                               TestC
 *======================================================================*/
void TestC()
{
	int i = 0x2000;
	while(1){
		if(p_proc_ready->ticks == p_proc_ready->total_ticks){
			if(!p_proc_ready->has_began){
				p_proc_ready->has_began=1;
				
				//p_sema(&s);
				
				p_sema(&r_mutex);
				if(r_count==0){p_sema(&w_mutex);}
				r_count++;
				if(r_count < MAX_READ_NUM){//如果已经达到最大读数量，就不再释放资源
					v_sema(&r_mutex);
				}
				
				//v_sema(&s);

				disp_color_str("C: r begin",RED_COLOR);
				disp_str(" / ");
			}
		}
		else if(p_proc_ready->ticks == 1){
			p_proc_ready->has_began=0;
			
			disp_color_str("C: r end",RED_COLOR);
			disp_str(" / ");
			
			if(r_count == MAX_READ_NUM){
				v_sema(&r_mutex);
			}
			r_count--;
			if(r_count==0){v_sema(&w_mutex);}
			
			/*if(r_count == MAX_READ_NUM){//该读进程结束时，如果已经达到最大读数量，就释放资源
				v_sema(&r_mutex);
			}
			p_sema(&r_mutex);
			r_count--;
			if(r_count==0){v_sema(&w_mutex);}
			v_sema(&r_mutex);*/
		}
		milli_delay(10);
	}
}

/*======================================================================*
                               TestD
 *======================================================================*/
void TestD()
{
	//int i = 0x2000;
	while(1){
		if(p_proc_ready->ticks == p_proc_ready->total_ticks){
			if(!p_proc_ready->has_began){
				p_proc_ready->has_began=1;
				
				//p_sema(&s);
				
				p_sema(&w_mutex);

				disp_color_str("D: w begin",GREEN_COLOR);
				disp_str(" / ");
			}
		}
		else if(p_proc_ready->ticks == 1){
			p_proc_ready->has_began=0;
			
			disp_color_str("D: w end",GREEN_COLOR);
			disp_str(" / ");
			
			v_sema(&w_mutex);
			
			//v_sema(&s);
		}
		
		/*if(p_proc_ready->sleep_ticks == 0){
			disp_str("D. ");
		}*/
		milli_delay(10);
	}
}

/*======================================================================*
                               TestE
 *======================================================================*/
void TestE()
{
	//int i = 0x2000;
	while(1){
		if(p_proc_ready->ticks == p_proc_ready->total_ticks){
			if(!p_proc_ready->has_began){
				p_proc_ready->has_began=1;
				
				//p_sema(&s);
				
				p_sema(&w_mutex);

				disp_color_str("E: w begin",GREEN_COLOR);
				disp_str(" / ");
			}
		}
		else if(p_proc_ready->ticks == 1){
			p_proc_ready->has_began=0;
			
			disp_color_str("E: w end",GREEN_COLOR);
			disp_str(" / ");
			
			v_sema(&w_mutex);
			
			//v_sema(&s);
		}
		
		milli_delay(10);
	}
}

/*======================================================================*
                               TestF
 *======================================================================*/
void TestF()
{
	//int i = 0x2000;
	while(1){
		//disp_int(p_proc_ready->ticks);
		if(p_proc_ready->ticks == 1){
			if(r_count==0){
				disp_str("F: w / ");
			}
			else{
				print_str("F: r: ");disp_int(r_count);print_str(" / ");
			}
		}
		milli_delay(10);
	}
}
